import { useFormMultiLanguage } from '@hooks/useFormMultiLanguage'
import draggable from 'vuedraggable';
import FormField from './MFormField';
import { FieldManager, SettingComponents, PreviewComponents } from './components';
import * as config from './config';
import Platform from '../platform';
import { cloneDeep, isEmpty } from 'lodash';
import { isSelect, getSameField } from './util';
import { findParentElementWithClassName, getRootWindow } from '@src/util/dom';
import { findComponentDownward } from '@src/util/assist'
import * as IMApi from '@src/api/ImApi.js';
import { useTenantId } from '@hooks/useRootWindow.ts';
import { useLocaleProvide } from '@hooks/useLocale'
/* api */
import { getEventList } from '@src/api/LinkcApi';
import { getDocumentList } from '@src/api/Repository'
import {
  getCompanyInfo,
  queryPartList,
  getPaasGrayFunctionList,
  commodityList
} from '@src/api/PortalApi.ts'
import BaseLanguageDropdown from '@src/component/common/BaseLanguageDropdown/index'
import { computed } from 'vue';
import i18n from '@src/locales'
/* mixin */
import { VersionControlProductMixin, VersionControlLinkCMixin } from '@src/mixins/versionControlMixin';
/* util */
import { isNotUndefined } from '@src/util/type';

/** 获取设置组件组件名，如果返回null，渲染默认组件 */
function getSettingComp(field, comp) {
  // 先检测是否有扩展设置
  let extend = comp.extend || {};
  let key = `${this.mode}_${field.fieldName}_setting`;
  
  // TODO: 当fieldName不固定且是系统字段
  let systemKey = `${this.mode}_${field.formType}_setting`;
  if (extend[key] || extend[systemKey]) return extend[key] || extend[systemKey];
  
  return comp.setting;
}

/** 创建字段设置组件 */
function createSettingComp(h, field) {
  if (null == field) return null;
  if (field.isHidden == 1) return null;
  
  let formType = field.formType;
  let comp = FieldManager.findField(formType);
  if (null == comp) return null;
  
  let compName = getSettingComp.call(this, field, comp);
  
  if (null == compName) {
    return (
      <div class="form-setting-panel">
        <h3 class="form-setting-panel-title">{field.displayName}</h3>
        <p class="form-design-warning">
          {i18n.t('common.form.tip.systemTemplateTips')}
        </p>
      </div>
    );
  }
    
  let props = { 
    field, 
    setting: comp, 
    mode: this.mode, 
    fields: this.value,
    eventList: this.eventList,
    wikiList: this.wikiList,
    hasWxAuth: this.hasWxAuth,
    wechatList: this.wechatList,
  };
  if (isSelect(field)) props.getContext = () => this;
  
  return h(compName, {
    ref: 'MFormDesignSetting',
    key: field._id,
    props,
    on: {
      input: event => {
        console.log('input', event);
        if (event.isSetting) {
          this.$set(field.setting, event.prop, event.value);
        } else {
          this.$set(field, event.prop, event.value);
        }
      },
      updateOptions: event => {
        this.updateOptions(field, event);
      }
    }
  });
}

/**
 * 判断元素是否可见
 * @param {*} el 判断的元素
 */
function isVisibility(el, container) {
  if (!el || !container) return
  
  let min = container.scrollTop;
  let max = min + container.offsetHeight;
  
  return min <= el.offsetTop && el.offsetTop + el.offsetHeight <= max;
}

const FormDesignV2 = {
  name: 'mform-design',
  mixins: [VersionControlProductMixin, VersionControlLinkCMixin],
  props: {
    mode: {
      type: String,
      default: 'base'
    },
    value: {
      type: Array,
      default: () => []
    },
    globalFields: {
      type: Array,
      default: () => []
    },
    /** 最大字段数量 */
    max: {
      type: Number,
      default: config.FORM_FIELD_MAX
    },
    /** 是否流程表单 */
    isFlowForm: {
      type: Boolean,
      default: false
    },
    index: {
      type: Number,
      default: 1
    },
    filterFields: {
      type: Array,
      default: () => []
    },
    isOpenRegister: {
      type: Boolean,
      default: false
    },
    typeId: {
      type: String,
      default: '',
    },
    templateName: {
      type: String,
      default: '',
    },
    themeColour: {
      type: String,
      default: '',
    },
    languageList: {
      type: Array,
      default: () => [],
    },
  },
  provide() {
    return {
      paasDataSource: this.paasDataSource,
    };
  },
  setup(props){
    const { locale: formPreviewLocale, setFormPreviewLocale } = useLocaleProvide('formPreviewLocale');
    const { isOpenMultiLanguage, languagesList } = useFormMultiLanguage()

    const languageMap = computed(() => {
      let language = (props.languageList ?? []).map(
        v => v.languageKey
      );
      return languagesList.filter(v => language.includes(v.languageKey));
    });

    function changeLocale(e){
      setFormPreviewLocale(e)
    }

    return {
      formPreviewLocale,
      changeLocale,
      isOpenMultiLanguage,
      languagesList,
      languageMap
    };
  },
  data() {    
    return {
      containerEl: null,
      // 角色列表
      roleList: [],
      // 产品关联字段
      productFields: [],
      // 表单模板列表
      formTemplateList: [],
      // 当前模式下可用字段
      availableFields: [],

      // 容器是否静默，不响应hover
      silence: false,

      // 是否拖拽中
      draggable: false,

      // 当前选择的字段
      currField: null,

      autographMax: config.AUTOGRAPH_MAX_LENGTH_MAX,
      show: false,
      eventList: [],
      wikiList: [],
      selectedCompNumber: [],
      imEnabled: false,
      hasWxAuth: false,
      wechatList: [],
      companyInfo: {},
      currentLang: '简体中文',
      partList: [],
      paasDataSource:{
        value:[]
      },
    };
  },
  computed: {
    formPreviewComponent() {
      return findComponentDownward(this, 'mform-preview') || {};
    },
    // 左侧控件分组
    fieldControls() {
      let fieldArr = [];
      let centerFields = ['enterpriseInfo', 'functionList', 'eventList'] // 个人中心专用组件
      if([1, 2].includes(this.index)){
        // 1：首页 2：服务
        let availableFields = this.availableFields.filter(v => !centerFields.includes(v.formType))
        let groupFields = availableFields.filter(
          item =>
            item.isSystem == 0
            && item.formType != 'info'
            && item.formType != 'separator'
        );
        let layoutFields = availableFields.filter(
          item => item.formType == 'info' || item.formType == 'separator'
        );
        let sysFields = availableFields.filter(f => f.isSystem == 1);
  
        if (groupFields.length) {
          if (this.filterFields.includes('productRegister')) {
            groupFields = groupFields.filter(v => v.formType !== 'productRegister')
          }
          let basisObj = {};
          basisObj.name = i18n.t('common.form.baseWidget');
          basisObj.field = groupFields;
          fieldArr.push(basisObj);
        }
        if (sysFields.length) {
          let sysObj = {};
          sysObj.name = i18n.t('common.form.systemWidget2');
          sysObj.field = sysFields;
          fieldArr.push(sysObj);
        }
        if (layoutFields.length) {
          let layoutObj = {};
          layoutObj.name = i18n.t('common.form.layoutWidget');
          layoutObj.field = layoutFields;
          fieldArr.push(layoutObj);
        }
      }else if([4].includes(this.index)){
        // 4：个人中心
        let personalFields = this.availableFields.filter(v => centerFields.includes(v.formType))
        if (personalFields.length) {
          let personalObj = {};
          personalObj.name = i18n.t('portal.personal');
          personalObj.field = personalFields;
          fieldArr.push(personalObj);
        }
      }

      return fieldArr;
    },
    tabbarFields() {
      return this.globalFields.find(item => item.formType === 'tabbar') || {};
    },
    // tabbarsList() {
    //   return this.globalFields[0]?.setting?.list || []
    // },
    isHiddenRightPanel() {
      return this.index === 3
    },
    isHiddenLeftPanel() {
      return (this.index === 3 ) && this.currField?.modular !== 'global'
    },
    isOpenServiceMall() {
      const RootWindow = getRootWindow(window);
      return RootWindow?.grayAuth?.SERVICE_MALL ?? false;
    }
  },
  watch: {
    mode: {
      handler(newValue) {
        this.setAvailableFields(newValue)
      },
      immediate: true
    }
  },
  methods: {
    initParams() {
      return {
        label: '', // 标签
        keyword: '', // 搜索的关键词
        orderDetail: {
          // 排序
          isSystem: 1,
          column: 'createtime',
          type: '',
          sequence: 'desc',
        },
        view: 'published',
        fasterFindId: '',
        allowShare: 1
      }
    },
    createTabbarComp(h, field) {
      if (!Object.keys(field).length) return null;

      let currFieldId = field.fieldName
      let previewComp = FieldManager.findField(field.formType);
      
      if (previewComp == null) {
        console.warn(
          `[not implement]: ${field.displayName}(${field.fieldName}): ${field.formType}. `
        );
        return null
      }
      
      // 根据字段配置创建预览内容
      if (!previewComp) return
      
      // 隐藏字段不渲染
      if (field.isHidden == 1) return
      
      let fieldPreview = h(previewComp.preview, {
        class: 'form-design__ghost',
        props: { field, setting: previewComp, disabled: true }
      });
      
      let previewClass = {
        'form-design-preview': true,
        // 被选中
        'form-design-selected': this.currField && currFieldId == this.currField.fieldName, 
        // 'form-design-error': field?.isError
      };
      
      return (
        <div
          class={previewClass}
          key={currFieldId}
          onClick={e => {
            e.stopPropagation();
            this.chooseField(field);
          }}
        >
          {fieldPreview}
        </div>
      );
    },
    setAvailableFields(mode) {
      let modeFields = FieldManager.findModeFields(mode || this.mode);
      // 可见字段(未被隐藏)
      let availableFields = [];
      
      modeFields.forEach(item => {
        let field = FieldManager.findField(item);
        if (null == field) return;
        
        availableFields.push(field);
      });
      this.availableFields = availableFields.filter(item => {
        
        const formTypeByVersionShowMap = {
          mall: this._isShowLinkCShop,
          productRegister: this._isShowProductRegister
        }
        
        if (['mall', 'productRegister'].includes(item.formType)) {
          const isShow = formTypeByVersionShowMap[item.formType]
          return isNotUndefined(isShow) ? isShow : false
        }
        
        return item
      })
    },
    changeSettingComponentIsValidateAll() {
      let settingComponent = this.$refs.MFormDesignSetting
      if (!settingComponent || !settingComponent.setValidateAll) return
      
      settingComponent.setValidateAll()
    },
    resetCurrentField() {
      this.currField = null
    },
    init() {
      this.getEventList();
      this.getWikiList();
      this.getImEnabled();
      this.getCompanyInfo();
      // this.getDoorTypeInfo();
      
      if (this.isOpenServiceMall) {
        this.getMallList();
      } else {
        this.getPartList();
      }

      this.getPaasGrayFunctionList()
      const openWeChatService = !!localStorage.getItem('openWeChatService') || false;
      if (openWeChatService) this.getAuthFlag();
    },
    getEventList() {
      getEventList().then(result => {
        if (result.status == 0) {
          this.eventList = result?.data || []
        }
      })
    },
    async getPaasGrayFunctionList() {
      const { code, data } = await getPaasGrayFunctionList();
      if (code == 0) {
        data?.map(v=>{
          v.text = v.templateName
          v.value = v.templateBizId
        })
        this.paasDataSource.value = data || [];
      }
    },
    // 获取知识库列表
    getWikiList() {
      const searchParams = this.initParams();
      // 先不允许分页，所以pageSize调了一个大值
      let params = {
        ...searchParams,
        pageNum: 1,
        pageSize: 1000
      }
      getDocumentList(params).then(result => {
        if (result.success) {
          this.wikiList = result?.result?.list || [];
        }
      })
    },
    // 获取在线客服设置总开关状态
    async getImEnabled() {
      try {
        const { code, data = false } = await IMApi.getImEnabled();
        if (code !== 0) return;
        this.imEnabled = !!data;
      } catch (error) {
        console.error('error', error);
      }
    },
    // 在线客服类型判断
    getAuthFlag() {
      IMApi.getAuthFlag().then(res => {
        const { code, data } = res;
        if (code !== 0) return;
        this.hasWxAuth = !!data;
        sessionStorage.setItem('hasWxAuth', this.hasWxAuth);
        this.wechatList = [];
        if (data == 1) this.getWeChatKFList();
      });
    },
    // 获取微信客服列表
    getWeChatKFList() {
      IMApi.getWeChatKFList().then(res => {
        const { code, data = [] } = res;
        if (code !== 0) return;
        this.wechatList = data;
      });
    },
    // 获取公司信息
    async getCompanyInfo() {
      try {
        const { code, result } = await getCompanyInfo({});
        if (code !== 0) return;

        this.companyInfo = result;
      } catch (error) {
        console.error('getCompanyInfo error', error);
      }
    },
    // 获取新版商城列表数据
    async getMallList() {
      try {
        const tenantId = useTenantId()?.value || '';
        const params = {
          pageNum: 0,
          pageSize: 10,
          keyWord: '',
          tenantId,
          type: 1,
        }
        const { code, data } = await commodityList(params);
        if (code !== '200') return;

        this.partList = data?.list || []
      } catch (error) {
        console.error('getMallList error', error);
      }
    },
    // 获取备件列表
    async getPartList() {
      try {
        const { code, data } = await queryPartList();
        if (code !== '200') return;

        this.partList = data?.list || []
      } catch (error) {
        console.error('getDoorTypeList error', error);
      }
    },
    changeLanguage(code) {
      // localStorage.setItem('shb-locale', code)
      this.$i18n.locale = code;
      this.currentLang = this.languageList.find(v => v.language === code)?.remark;
    },
    /** 触发input事件 */
    emitInput(value) {
      this.$emit('input', value);
    },
    /** 开始插入字段 */
    beginInsert(field, isDisabled) {
      // 商城和个人中心页面不允许添加组件
      if (this.index == 3 || this.index == 4) return;

      // 在线客服在企业版才可使用
      if (field.name === '在线客服' && !this.imEnabled) return;
      // 禁止拖拽
      if (this.draggingDisable(field) || isDisabled) return;
      
      // 限制字段数量
      if (this.value.length >= this.max) {
        return Platform.alert(i18n.t('common.form.setting.formFieldMaxCountTips', {data1:this.max}))
      }
      
      // 限制电子签名字段数量
      let autographFields = this.value.filter(
        field => field.formType == 'autograph'
      );
      if (
        autographFields.length >= this.autographMax
        && field.formType === 'autograph'
      ) {
        return Platform.alert(i18n.t('common.form.setting.formSignFieldMaxCountTips', {data1:this.autographMax}));
      }
      
      this.currField = null
    },
    /** 添加新字段 */
    insertField(option = {}, value, index) {
      let newField = new FormField({
        ...option,
        formType: option.formType,
        displayName: option.name,
        fieldName: option.fieldName,
        isSystem: option.isSystem,
        setting: {}
      });

      let arr = cloneDeep(value ? value : this.value);
      index == null ? arr.push(newField) : arr.splice(index, 0, newField);
      this.emitInput(arr);

      this.chooseField(newField);
      return newField;
    },
    /** 立即插入字段 */
    immediateInsert(field, isDisabled) {
      if (this.index == 3 || this.index == 4) return;

      // 在线客服在企业版才可使用
      if (field.name === '在线客服' && !this.imEnabled) return;

      // 禁止拖拽
      if (this.draggingDisable(field) || isDisabled) return;

      // 限制字段数量
      if (this.value.length >= this.max) {
        return Platform.alert(i18n.t('common.form.setting.formFieldMaxCountTips', {data1:this.max}));
      }
      
      this.insertField(field, this.value, this.value.length);
      
      // 增加组件滚动到底部
      this.$nextTick(() => {
        let previewEl = this.$el.querySelector('.form-design-phone');
        previewEl.scrollTop = previewEl.scrollHeight;
      })
    },
    /** 选中字段 */
    chooseField(field) {
      this.currField = field;
      this.$nextTick(() => {
        let draggingEl = this.$el.querySelector('.form-design-selected');
        let containerEl = findParentElementWithClassName(
          draggingEl,
          'form-preview'
        );
        
        if (!draggingEl || !containerEl) return
        
        let visible = isVisibility.call(this, draggingEl, containerEl);
        
        if (!visible) {
          let scrollTop = (
            draggingEl.offsetTop 
            + draggingEl.offsetHeight 
            - containerEl.offsetHeight
          )
          
          containerEl.scrollTop = scrollTop;
        }
        
      });
    },
    /** 禁止拖拽 */
    draggingDisable(field) {
      return field.isSystem === 1
        ? this.value.findIndex(v => v.formType == field.formType) > -1
        : false;
    },
    /** 关闭弹窗 */
    onCloseBaseModal() {
      this.show = false;
    },
    /** 更新options */
    updateOptions(field, event) {
      if (!field.setting.customerOption) return;
      field.setting.customerOption[event.prop] = event.value;
    },
    /** 恢复已隐藏字段 */
    async onRestoreField(row) {
      let field = getSameField(this.value, row.fieldName);
      field.isHidden = 0;
      
      this.emitInput(this.value);
      this.$platform.notification({
        title: i18n.t('common.base.tip.operationSuccess'),
        type: 'success'
      });
    },
    /** 渲染字段分组头部 */
    renderTabHeader(name) {
      return (
        <div class="form-design-tabs">
          <div class="form-design-tab">{name}</div>
        </div>
      );
    },
    updateCompNumber(value) {
      this.selectedCompNumber = value;
    },
    /** 渲染分组字段 */
    renderFieldList(fields) {
      if (fields.length == 0) {
        return (
          <div class="form-design-field-empty">
            { this.fieldGroup == 0 ? i18n.t('common.form.setting.renderFieldListTips1') : i18n.t('common.form.setting.renderFieldListTips2')}
          </div>
        );
      }
      
      return fields.map(field => {
        const isDisabled = this.selectedCompNumber[field.formType] && this.selectedCompNumber[field.formType] === field.number;
        return (
          <div
            class={[
              'form-design-field-wrap',
              { disabled: isDisabled || this.draggingDisable(field) || (field.name === '在线客服' && !this.imEnabled)}
            ]}
            onMousedown={e => this.beginInsert(field, isDisabled)}
            onClick={() => {
              this.beginInsert(field, isDisabled);
              this.immediateInsert(field, isDisabled);
            }}
          >
            {
              field.name === '在线客服' && !this.imEnabled 
                ? <el-tooltip effect="dark" content={i18n.t('portal.portalTip13')} placement="top-start">
                  <i class="iconfont icon-jinggao tips"></i>
                </el-tooltip> : ''
            }
            <div class={['form-design-field form-design__ghost', {'checked': this.currField && (this.currField.formType === field.formType)}]}>
              {/* <span class="anticon">å
                <i class={['iconfont', `icon-fdn-${field.formType}`]}></i>
              </span> */}
              <i class={['iconfont', `${field.icon}`]}></i>
              <span class="field-title">{field.name}</span>
              <span class="field-number">{this.selectedCompNumber[field.formType] ? this.selectedCompNumber[field.formType] : 0} / {field.number}</span>
            </div>
          </div>
        );
      });
    },
    /** 渲染设置组件 */
    renderSettingPanel(h) {
      let fieldSetting = createSettingComp.call(this, h, this.currField);
      
      return (
        <div 
          class={['form-design-setting', 'mform-design-setting']} 
          key="form-design-setting"
          style={this.isHiddenLeftPanel ? {opacity: 0} : {opacity: 1}}
        >
          {fieldSetting}
        </div>
      );
    },
    cloneData(option) {
      return new FormField({
        ...option,
        formType: option.formType,
        displayName: option.name,
        fieldName: option.fieldName,
        isSystem: option.isSystem,
        setting: {}
      })
    }
  },
  render(h) {
    const item = this.languageList.map(item => {
      return (
        <el-dropdown-item command={item.language}>
          {item.remark}
        </el-dropdown-item>
      )
    })

    return (
      <div class="form-design">
        <div 
          class="form-design-panel" 
          style={this.isHiddenRightPanel ? {opacity: 0} : {opacity: 1}} 
        >
          <div class="form-design-left">
            {this.fieldControls.map(field => {
              return (
                <div class="form-design-widget">
                  {this.renderTabHeader(field.name)}
                  <draggable
                    animation="180"
                    tag="div"
                    group={{
                      name: 'widget',
                      pull: 'clone',
                      put: false
                    }}
                    sort={false}
                    filter=".disabled"
                    value={field.field}
                    clone={this.cloneData}
                    class="form-design-tabs-content"
                    onStart={() => {
                      this.draggable = true;
                      this.formPreviewComponent.backupValue = cloneDeep(this.value)
                    }}
                    onEnd={() => {
                      this.draggable = false;
                    }}
                  >
                    {this.renderFieldList(field.field)}
                  </draggable>
                </div>
              );
            })}
          </div>
        </div>
        <div class="form-design-main">
          <div class="form-design-config">
            <span>{i18n.t('common.base.preview')}</span>
            <div 
              class="form-design-language" 
              style={this.index !== 3 && this.isOpenMultiLanguage ? {display: 'block'} : {display: 'none'}} 
            >
              {/* <el-dropdown onCommand={(command) => this.changeLanguage(command)}>
                <span>{this.currentLang}<i class="el-icon-arrow-down"></i></span>
                <el-dropdown-menu slot="dropdown">
                  {item}
                </el-dropdown-menu>
              </el-dropdown> */}
              <div class="flow-preview-header">
                <BaseLanguageDropdown class="flow-preview-header-translate" options={this.languageMap} lang={this.formPreviewLocale} onChange={this.changeLocale} />
              </div>
            </div>
          </div>
          <div class="form-design-box">
            <div class="form-design-center">
              <div class="form-design-header">
                <h3>{this.templateName || ''}</h3>
              </div>
              <div
                class={[
                  'form-design-phone',
                  this.silence ? 'form-design-silence' : null
                ]}
              >
                <mform-preview 
                  value={this.value} 
                  filterFields={this.filterFields} 
                  updateCompNumber={this.updateCompNumber} 
                  index={this.index} 
                />
              </div>
              <div class="form-design-footer">
                {this.createTabbarComp(h, this.tabbarFields)}
              </div>
            </div>
          </div>
        </div>
        {this.renderSettingPanel(h)}
      </div>
    );
  },
  mounted() {
    this.init();
  },
  components: { draggable, ...SettingComponents, ...PreviewComponents }
};

export default FormDesignV2;
